package app.controllers;

import app.Const;
import app.constant.DictConstant;
import app.constant.OrderConstant;
import app.constant.ProductConstant;
import app.kit.CommonKit;
import app.kit.TypeKit;
import app.models.basic.Dict;
import app.models.basic.Notes;
import app.models.member.Member;
import app.models.member.RiskRule;
import app.models.order.Order;
import app.models.product.Brand;
import app.models.product.Details;
import app.models.product.Product;
import app.services.OrderService;
import app.services.bus.BusContext;
import bank.BankService;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jfinal.aop.Before;
import com.jfinal.ext.interceptor.GET;
import com.jfinal.plugin.activerecord.Page;
import goja.GojaConfig;
import goja.StringPool;
import goja.Validator;
import goja.mvc.AjaxMessage;
import goja.mvc.Controller;
import goja.mvc.kit.Servlets;
import goja.rapid.db.RequestParam;
import goja.security.goja.SecurityKit;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.joda.time.DateTime;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static app.Const.FIELD_COLLECTION_MODE;
import static app.Const.FIELD_TIME_LIMIT_UNIT;

/**
 * <p>
 * The url home Controller.
 * </p>
 *
 * @author sagyf yang
 * @version 1.0
 * @since JDK 1.6
 */
public class ProductController extends Controller {

    private static final List<String> order_fields = Lists.newArrayList(Const.FIELD_YIELD, "due_date", Const.FIELD_PRICE);

    /**
     * WEB产品列表
     * <p/>
     * {brand}-{timeType}-{statusType}-{sort}?page=1&pageSize=12
     * page       页码
     * sort  排序字段 field_dir like  yield_asc
     * brand      品牌ID
     * timeType   期限区间 1: 0-10天, 2: 10-30天 3: 1-3个月 4: 3-6个月 5: 6-12个月
     * statusType 状态  1-上线 2-售罄 4-到期
     * pageSize   每页显示数量
     */
    @Before(GET.class)
    public void index() {
        setAttr("curent", 2);
        int page = getParaToInt("page", 1);
        int pageSize = getParaToInt("pageSize", 12);
        int brand = getParaToInt(0, 0);
        int timeType = getParaToInt(1, 0);
        int statusType = getParaToInt(2, 0);
        String sort = getPara(3, StringPool.EMPTY);
        String sort_field = StringPool.EMPTY;
        String sort_dir = StringPool.EMPTY;
        if (!Strings.isNullOrEmpty(sort)) {
            final int sort_index = sort.lastIndexOf("_");
            sort_field = sort.substring(0, sort_index);
            sort_dir = sort.substring(sort_index+1);
            if (order_fields.contains(sort_field)) {
                if (StringUtils.equals("asc", sort_dir)) {
                    sort_dir = "ASC";
                } else if (StringUtils.equals("desc", sort_dir)) {
                    sort_dir = "DESC";
                }
            }
        }

        final RequestParam.Direction sort_direction = Strings.isNullOrEmpty(sort_dir) ? null :
                RequestParam.Direction.valueOf(sort_dir);
        Page<Product> results = Product.dao.findByPageList(page, pageSize,
                sort_field, sort_direction,
                brand, timeType, statusType);
        setAttr("data", results);
        setAttr("brand", brand);
        setAttr("timeType", timeType);
        setAttr("statusType", statusType);
        setAttr("sort_field", sort_field);
        List<Brand> brands = Brand.dao.findAll();
        setAttr("brands", brands);

        if(sort_direction != null){
            setAttr("sort_dir", sort_direction == RequestParam.Direction.DESC ? "asc" : "desc");
        }
        final DateTime now = DateTime.now();
        setAttr("nowhour", now.getHourOfDay());

        render("../product.ftl");
    }


    public void item() {
        setAttr("curent", 2);
        int pid = getParaToInt(0, 0);
        if (pid > 0) {



            BigDecimal purchaseAmount = CommonKit.getPurchaseAmount();
            setAttr("purchasedaily", purchaseAmount.toPlainString());
            // 产品信息
            Product product = Product.dao.findByWebIntro(pid);
            if(product == null){
                redirect("/product");
                return;
            }
            setAttr(Const.FIELD_PRODUCT, product);
            // 产品描述

            List<Details> productDetailses = Details.dao.findByWebItem(pid);

            setAttr("intros", productDetailses);

//            setAttr("risk_txt", Dict.dao.getRiskLevel(TypeKit.getInt(product, Const.FIELD_RISK_TOLERANCE)));
            setAttr(FIELD_TIME_LIMIT_UNIT, Dict.getTimeLimit(product.getStr(FIELD_TIME_LIMIT_UNIT)));
            setAttr(FIELD_COLLECTION_MODE, Dict.dao.collection_mode_map(product.getNumber(FIELD_COLLECTION_MODE).intValue()));


            setAttr("project_json", product.toJson());

            setAttr("jump_url", GojaConfig.getProperty("bank.epcs.url"));

            setAttr("risk_txt", Notes.dao.findByRisk());
            setAttr("buy_txt", Notes.dao.findByBuy());
            setAttr("notes_buy", Notes.dao.findByBuy());

            Details riskByProduct = Details.dao.findRiskByProduct(pid);
            setAttr("details", riskByProduct!=null?riskByProduct.getStr("attribute_val"):StringPool.EMPTY);

            setAttr("nowhour", DateTime.now().getHourOfDay());
            render("info.ftl");

            // 访问纪录
            final HttpServletRequest request = getRequest();
            int memberId = SecurityKit.isLogin(request)? SecurityKit.getLoginUser(request).getNumber(StringPool.PK_COLUMN).intValue() : 0;
            BusContext.postAccess(memberId, pid, DateTime.now(), Servlets.getIp(request));
        } else {
            renderError(404);
        }

    }

    /**
     * 立即投资
     */
    public void investment() {
        int product_id = getParaToInt(0, 0);
        if (product_id > 0) {

//            String orderId = getPara("order");

            final HttpServletRequest request = getRequest();
            if (!SecurityKit.isLogin(request)) {
                renderAjaxNologin();
                return;
            }

            // 1. 看会员有没有风险评级，没有，则进行提示进行风险评级
            final Member member = SecurityKit.getLoginUser(request);

            int risk_tolerance = TypeKit.getInt(member, Const.FIELD_RISK_TOLERANCE);

            if (risk_tolerance <= 0) {
                renderJson(AjaxMessage.failure(StringPool.EMPTY, 1, null));
                return;
            }


            String amonut_str = getPara(Const.FIELD_AMOUNT);

            // 日购买限制
            BigDecimal purchaseAmount = CommonKit.getPurchaseAmount();
            // 查询会员今日购买的

            DateTime now = DateTime.now();
            DateTime.Property property = now.millisOfDay();
            DateTime start = property.withMinimumValue();
            DateTime end = property.withMaximumValue();
            BigDecimal sumAmount = Order.dao.sumAmountByMember(member.getId(), start, end);
            if (sumAmount.compareTo(purchaseAmount) >= 0) {
                // 如果购买超过当前金额，则进行提示
                renderAjaxFailure("您的当日累计投资金额不得超过"+ purchaseAmount.toPlainString() + "元!");
                return;
            }

            if (Strings.isNullOrEmpty(amonut_str)) {
                renderAjaxFailure("请输入投资金额");
                return;
            }

            if (!Validator.isCurrency(amonut_str)) {
                renderAjaxFailure("请输入正确的投资金额，应该只有小数点和数字的组合");
                return;
            }
            final Product product = Product.dao.findById(product_id);
            if (product == null) {
                renderAjaxFailure("请选择购买投资产品");
                return;
            }
            if (product.getNumber(Const.FIELD_STATUS).intValue() != ProductConstant.ONLINE) {
                renderAjaxFailure("产品不在销售期内，无法交易");
                return;
            }

            // 产品等级

            // 2. 如果会员有风险评级，则读取该产品的等级
            final int risk_level = TypeKit.getInt(product, Const.FIELD_RISK_TOLERANCE);
            RiskRule riskRule = RiskRule.dao.findByProductLevel(risk_tolerance);
            if (!StringUtils.contains(riskRule.getStr("risk_level"), String.valueOf(risk_level))) {
                renderJson(AjaxMessage.failure(StringPool.EMPTY, 2, null));
                return;
            }


            if (Strings.isNullOrEmpty(member.getStr("electronic_account"))) {
                renderJson(AjaxMessage.failure("请先绑定电子账户后在进行投资", 3, null));
                return;
            }

            BigDecimal amount = NumberUtils.createBigDecimal(amonut_str);

            // 判断价格

            if (amount.compareTo(purchaseAmount) > 0) {
                // 如果购买超过当前金额，则进行提示
                renderAjaxFailure("您的当日累计投资金额不得超过"+ purchaseAmount.toPlainString() + "元!");
                return;
            }
            final BigDecimal price = product.getBigDecimal("price");
            if (amount.compareTo(price) > 0) {
                renderAjaxFailure("投资金额不能超过" + price + "元");
                return;
            }
            final BigDecimal max_invest_amount = product.getBigDecimal("max_invest_amount");
            final BigDecimal min_invest_amount = product.getBigDecimal("min_invest_amount");
            final BigDecimal increase_amount = product.getBigDecimal("increase_amount");
            // 剩余可投金额
            final BigDecimal remaining_amount = product.getBigDecimal("remaining_amount");
            if(remaining_amount.compareTo(BigDecimal.ZERO) <= 0){
                renderAjaxFailure("募集资金已经完成，无法继续投资.");
                return;
            }
            if(amount.compareTo(remaining_amount) == 1){
                renderAjaxFailure("投资金额不能超过" + remaining_amount.toPlainString() + "元!");
                return;
            }
            if(amount.compareTo(max_invest_amount) == 1){
                renderAjaxFailure("单笔投资不能超过" + max_invest_amount.toPlainString() + "元");
                return;
            }
            if(amount.compareTo(min_invest_amount) == -1){
                renderAjaxFailure("最小投资金额为" + min_invest_amount.toPlainString() + "元");
                return;
            }
            if (BigDecimal.ZERO.compareTo(amount.remainder(increase_amount)) != 0) {
                renderAjaxFailure("投资金额必须为" + increase_amount.toPlainString() + "的整数倍");
                return;
            }

            final Map<String, Object> results = Maps.newHashMapWithExpectedSize(6);

            Order order;
//            if (!Strings.isNullOrEmpty(orderId)) {
//                // 传递已经生成的订单ID
//                order = Order.dao.findById(orderId);
//                if (order == null) {
//                    order = OrderService.me().createOrder(member, product, OrderConstant.BUY_TYPE, amount);
//                } else {
//                    order.set("trade_amount", amount);
//                    order.update();
//                }
//            } else {
                order = OrderService.me.createOrder(member, product, OrderConstant.BUY_TYPE, amount);
//            }


            results.put("order", order);

            // 计算 起息和到息
            DateTime valueDate = TypeKit.getDateTime(product, "valuedate");
            if (valueDate == null) {
                valueDate = DateTime.now();
            }
            DateTime due_date = TypeKit.getDateTime(product, "due_date");
            final String time_limit_unit = product.getStr(FIELD_TIME_LIMIT_UNIT);
            if (due_date == null) {
                final int time_limit = TypeKit.getInt(product, Const.FIELD_TIME_LIMIT);
                if (StringUtils.equals(time_limit_unit, DictConstant.MONTH_UNIT)) {
                    due_date = valueDate.plusMonths(time_limit);
                } else {
                    due_date = valueDate.plusDays(time_limit);
                }
            }

            results.put(FIELD_TIME_LIMIT_UNIT, Dict.getTimeLimit(time_limit_unit));
            final Date begin_interest = valueDate.toDate();
            results.put("begin_interest", begin_interest);
            results.put("end_interest", due_date.toDate());

            results.put(Const.FIELD_RISK_TOLERANCE, risk_tolerance);

            results.put(Const.FIELD_PRODUCT, product);


            final String productName = product.getStr(Const.FIELD_NAME);
            final String memberCode = member.getStr(Const.FIELD_CODE);
            final String orderCode = order.getStr("trade_no");
            DateTime nowtime = DateTime.now();
            final Optional<Map<String, String>> oks = BankService.me.nopwdCreateOrderSign(nowtime, nowtime, memberCode, orderCode,
                    "购买[" + productName + "] 产品", "投资购买" + productName + "产品，融理财富平台", amonut_str,
                    GojaConfig.domain() + "pay/tip", GojaConfig.domain() + "pay/asyn");
            if (oks.isPresent()) {
                results.put("pay", oks.get());
            } else {
                renderAjaxFailure("系统发生错误，请稍后再试");
                return;
            }

            renderAjaxSuccess(results);

        } else {
            renderAjaxFailure();
        }
    }
}